﻿#include "Student.h"

bool cmp(Stu a, Stu b);

int Student::Snum = 0;

//	初始化学生总数
void Student::getSnum()
{
	Stu* student = new Stu;
	int sno = -1;					//	用于比较学号是否一致
	ifstream file("Student.txt", ios::in);
	if (!file.fail())
	{
		while (!file.eof())
		{
			file >> student->sno >> student->name >> student->sex >> student->ca;
			for (int i = 0; i < 5; ++i) file >> student->score[i];

			//	由于当保存学生的文件中最后一行是回车时，循环还会在循环一次，学生人数多一，因此需要判断
			if (sno == -1) sno = student->sno;
			else if (sno == 0 || sno == student->sno) break;
			else sno = student->sno;
			Snum++;
		}
	}
	file.close();
	delete student;
}

//	录入学生信息
void Student::input()
{
	cout << "你要输入多少名学生的信息:";
	int n;
	cin >> n;
	Snum += n;					//	学生总数增加n

	system("cls");				//	清屏

	Stu* student = new Stu;

	ofstream ofile("Student.txt", ios::app | ios::out);
	if (!ofile.fail())
	{
		for (int i = 0; i < n; i++)
		{
			cout << "第" << i + 1 << "位学生 共" << n  << "位" << endl;
			cout << "请输入学生学号：";
			cin >> student->sno;
			cout << "请输入学生姓名：";
			cin >> student->name;
			cout << "请输入学生性别（男：1 女：0）：";
			cin >> student->sex;
			cout << "请输入学生班级：";
			cin >> student->ca;
			for (int i = 0; i < 5; i++)
			{
				cout << "请输入专业课" << i + 1 << "成绩：";
				cin >> student->score[i];
			}
			cout << endl;

			ofile << student->sno << '\t' << student->name << '\t' <<  student->sex << '\t' << student->ca;
			for (int i = 0; i < 5; i++)
			{
				ofile << '\t' << student->score[i];
			}
			ofile << endl;
		}
		ofile.close();
		delete student;
	}
}

//	修改学生成绩
void Student::setScore()
{
	Stu* student = new Stu[Snum];
	int m(0), k(0), inquire(0);    //m保存要修改的专业课下标 k保存查询到的学生下标 inquire保存查询结果
	//	查询学生
	while (1)
	{
		do
		{ 
			inquire = inquireStudent(&k, student);
			if (inquire == 3) return;
			else if (inquire == 1) break;
			Sleep(750);			//	程序休眠750ms
			system("cls");		//	清屏
		} while (1);
		
		cout << "\n这是需要修改的学生吗？" << endl;
		cout << "是：y 否：n" << endl;
		string yon;
		cin >> yon;
		if (yon == "y")break;
		system("cls");		//	清屏
	}

	//	修改专业
	cout << "请选择要修改的专业课：";
	cin >> m;                                   //m：储存要修改的专业课
	cout << "请输入该专业课成绩：";
	double cj;                                  //cj：专业课成绩
	cin >> cj;
	student[k].score[m - 1] = cj;

	//	将修改后的结果输出屏幕
	system("cls");
	cout << "学号\t姓名\t性别\t班级\t专业课1\t专业课2\t专业课3\t专业课4\t专业课5" << endl;
	cout << student[k].sno << '\t' << student[k].name;
	printSex(student[k].sex);
	cout << student[k].ca;
	for (int j = 0; j < 5; ++j) cout << '\t' << student[k].score[j];

	//	将修改后的数据覆盖原文件
	ofstream ofile;
	ofile.open("Student.txt", ios::trunc);
	if (!ofile.fail())
	{
		for (int i = 0; i < Snum; i++)                    //Snum 为录入学生数
		{
			ofile << student[i].sno << "\t" << student[i].name << "\t" << student[i].sex << "\t" << student[i].ca;
			for (int j = 0; j < 5; j++)
			{
				ofile << '\t' << student[i].score[j];
			}
			ofile << endl;
		}
	}
	ofile.close();

	delete[]student;
}
	
//	删除学生信息
void Student::popStudent()
{
	Stu* student = new Stu[Snum];
	int k(0), inquire(0);			// k保存查询到的学生下标 inquire保存查询结果
	//	查询学生
	while(1)
	{
		do
		{
			inquire = inquireStudent(&k, student);
			if (inquire == 3) return;
			else if (inquire == 1) break;
			Sleep(750);				//	程序休眠750ms
			system("cls");
		} while (1);
		cout << "\n这是需要删除的学生吗？" << endl;
		cout << "是：y 否：n" << endl;
		string yon;
		cin >> yon;
		if (yon == "y") break;
		system("cls");
	}

	//	将修改后的数据覆盖原文件
	ofstream ofile;
	ofile.open("Student.txt", ios::trunc);
	if (!ofile.fail())
	{
		for (int i = 0; i < Snum; i++)                    //Snum 为录入学生数
		{
			if (i == k)continue;
			ofile << student[i].sno << "\t" << student[i].name << "\t" << student[i].sex << "\t" << student[i].ca;
			for (int j = 0; j < 5; j++)
			{
				ofile << '\t' << student[i].score[j];
			}
			ofile << endl;
		}
	}
	ofile.close();
	Snum--;						//	学生总数减少1
	cout << "删除成功!" << endl;
	delete[]student;
}

//	增加学生信息
void Student::addStudent()
{
	Stu* student = new Stu;

	ofstream ofile;
	ofile.open("Student.txt", ios::app | ios::out);
	if (!ofile.fail())
	{
		cout << "请输入学生学号：";
		cin >> student->sno;
		cout << "请输入学生姓名：";
		cin >> student->name;
		cout << "请输入学生性别（男：1 女：0）：";
		cin >> student->sex;
		cout << "请输入学生班级：";
		cin >> student->ca;
		for (int i = 0; i < 5; ++i)
		{
			cout << "请输入专业课" << i + 1 << "成绩：";
			cin >> student->score[i];
		}
		cout << endl;
		ofile << student->sno << '\t' << student->name << '\t' << student->sex << '\t' << student->ca;
		for (int i = 0; i < 5; i++)
		{
			ofile << '\t' << student->score[i];
		}
		ofile << endl;
	}
	ofile.close();
	Snum++;				//	学生总数增加1
	delete student;
}

//	计算每位学生的总分与平均分
void Student::total()
{
	cout << "学号\t姓名\t性别\t班级\t总分\t平均分" << endl;

	Stu* student = new Stu;
	ifstream ifile("Student.txt", ios::in);
		if (!ifile.fail())
		{
			for (int i = 0; i < Snum; i++)
			{
				ifile >> student->sno >>student->name >> student->sex >> student->ca;
				double pjf = 0; double zf = 0;			// pjf平均分 zf总分
				//	计算总分
				for (int i = 0; i < 5; i++)
				{
					ifile >> student->score[i];
					zf += student->score[i];
				}
				//	计算平均分
				pjf = zf / 5;

				//	输出
				cout << student->sno << '\t' << student->name;
				printSex(student->sex);
				cout << student->ca << '\t' << zf << '\t' << pjf << endl;
			}
		}
		ifile.close();
		delete student;
}

//	查询学生信息
int Student::inquireStudent(int* k, Stu* student)
{
	ifstream ifile;
	ifile.open("Student.txt", ios::in);
	if (!ifile.fail())
	{
		for (int i = 0; i < Snum; i++)                    //Snum 为录入学生数
		{
			ifile >> student[i].sno >> student[i].name >> student[i].sex >> student[i].ca;
			for (int j = 0; j < 5; j++)
			{
				ifile >> student[i].score[j];
			}
		}
	}
	ifile.close();

	int n, i(0);			//	n功能选项 i学生下标
	string name;
	while (1)
	{
		cout << "请选择查询方式" << endl;
		cout << "1. 学号查询" << endl;
		cout << "2. 姓名查询" << endl;
		cout << "0. 返回主菜单" << endl;
		cin >> n;
		system("cls");

		if (n != 0 && n != 1 && n != 2)
		{
			cout << "输入选项不正确!请重新输入!" << endl;
			Sleep(750);
			system("cls");
			continue;
		}

		i = 0;
		switch (n)
		{
		case 1:
			LL a;
			cout << "请输入学生学号：";
			cin >> a;

			for (; i < Snum; i++)
			{
				if (student[i].sno == a)
				{
					*k = i;
					break;
				}
			}
			if (i == Snum)
			{
				cout << "无法查询到该学生信息！" << endl;
				return 0;
			}
			break;
		case 2:
			cout << "请输入学生姓名：";
			cin >> name;
			for (; i < Snum; i++)
			{
				if (name == student[i].name)
				{
					*k = i;
					break;
				}
			}
			if (i == Snum)
			{
				cout << "无法查询到该学生信息！" << endl;
				return 0;		//	无法查询到返回0
			}
			break;
		case 0:
			return 3;			//	取消查询返回3
		}
		break;
	}
	
	//	打印
	cout << "成功查询到该学生信息！\n\n";
	cout << "学号\t姓名\t性别\t班级\t专业课1\t专业课2\t专业课3\t专业课4\t专业课5" << endl;
	cout << student[*k].sno << '\t' << student[*k].name;
	printSex(student[*k].sex);
	cout << student[*k].ca;
	for (int i = 0; i < 5; ++i) cout << '\t' << student[*k].score[i];
	cout << endl;
	return 1;			//	查询成功返回1
}


//	按班级查询学生信息
bool Student::inquireClass(bool isprint, vector<Stu>* _student)
{
	string ca;
	cout << "请输入要查询的班级：";
	cin >> ca;
	//	判断是否需要输出打印格式
	if (isprint) cout << "学号\t姓名\t性别\t专业课1\t专业课2\t专业课3\t专业课4\t专业课5" << endl;

	Stu* student = new Stu;
	bool j(0);			//	保存是否查询到班级
	ifstream ifile("Student.txt", ios::in);
	if (!ifile.fail())
	{
		for (int i = 0; i < Snum; i++)
		{
			ifile >> student->sno >> student->name >> student->sex >> student->ca;
			for (int i = 0; i < 5; i++)
			{
				ifile >> student->score[i];
			}

			//	判断是否是该班级学生
			if (ca != student->ca) continue;
			j = true;

			//	判断是否需要输出打印学生信息
			if (isprint)
			{
				cout << student->sno << '\t' << student->name;
				printSex(student->sex);
				for (int j = 0; j < 5; ++j) cout << student->score[j] << '\t';
				cout << endl;
			}
			else
			{
				_student->push_back(*student);
			}
		}
		
	}
	ifile.close();
	delete student;
	if (!j)
	{
		cout << "无法查寻到此班级" << endl;
		return false;
	}
	return true;
}

//	成绩排序
void Student::gradeRanking()
{
	Stu* student = new Stu[Snum];
	ifstream file("Student.txt", ios::in);
	if (!file.fail())
		for (int i = 0; i < Snum; ++i)
		{
			file >> student[i].sno >> student[i].name >> student[i].sex >> student[i].ca;
			for (int j = 0; j < 5; ++j)
			{
				file >> student[i].score[j];
				student[i].average += student[i].score[j];
			}
			student[i].average /= 5.0;
		}
	file.close();
	//	按平均分排序
	sort(student, student + Snum, cmp);
	
	string s;		//	排序方式选择
	bool px(0);		//	排序方式保存
	while (1)
	{
		cout << "请确认排序方式！" << endl;
		cout << "1. 降序  2. 升序" << endl;
		cin >> s;

		if (s == "1") px = false;
		else if (s == "2") px = true;
		else
		{
			cout << "输入选项不正确！请输入正确选项！";
			Sleep(850);
			system("cls");
			continue;
		}
		break;
	}
	system("cls");

	cout << "学号\t姓名\t性别\t班级\t专业课1\t专业课2\t专业课3\t专业课4\t专业课5\t平均分" << endl;
	int i(-1);
	if (!px) i = Snum;
	while((px && ++i < Snum) || (!px && --i >= 0))
	{
		cout << student[i].sno << '\t' << student[i].name;
		printSex(student[i].sex);
		cout << student[i].ca;
		for (int j = 0; j < 5; ++j) cout << '\t' << student[i].score[j];
		cout << '\t' << student[i].average << endl;
	}
}

//	排序规则
bool cmp(Stu a, Stu b)
{
	if (a.average < b.average) return true;
	else if (a.average == b.average && a.sno < b.sno) return true;
	return false;
}

//按班级统计学科不及格人数
void Student::classFlunkNum()
{
	vector<Stu> student;

	//	查询班级，并保存学生
	while (!inquireClass(false, &student))
	{
		Sleep(850);
		system("cls");
		cout << "是否重新输入？" << endl;
		cout << "1：重新输入 0：取消并返回主菜单" << endl;
		string ison;
		cin >> ison;
		if (ison == "0") return;
	}

	//	统计不及格人数
	LL num[5];			//	保存各专业不及格人数
	memset(num, 0, sizeof(num));			//	初始化数组
	for (size_t i = 0; i < student.size(); ++i)
		for (int j = 0; j < 5; ++j)
			if (student[i].score[j] < 60)
				num[j]++;

	//	打印
	cout << "该班级总人数：" << student.size() << endl;
	cout << "专业课1不及格人数\t专业课2不及格人数\t专业课3不及格人数\t专业课4不及格人数\t专业课5不及格人数" << endl;
	for (int i = 0; i < 5; ++i)
		cout << ' ' << num[i] << "\t\t\t";

	vector<Stu>().swap(student);
}

//	输出学生性别
void Student::printSex(bool sex)
{
	if (sex) cout << "\t男\t";
	else cout << "\t女\t";
}